package com.lktx.bbfactory.controller;

import com.alibaba.excel.EasyExcel;
import com.lktx.bbfactory.common.CommonResult;
import com.lktx.bbfactory.common.exception.BizAsserts;
import com.lktx.bbfactory.common.hander.ProductTemplateDropdownWriteHandler;
import com.lktx.bbfactory.entiy.DTO.GanttConfigDto;
import com.lktx.bbfactory.entiy.DTO.productDto.*;
import com.lktx.bbfactory.entiy.DTO.ProjectExcelDTO;
import com.lktx.bbfactory.entiy.Product;
import com.lktx.bbfactory.entiy.Project;
import com.lktx.bbfactory.service.productService;
import com.lktx.bbfactory.service.projectService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/excel")
public class ExcelController {

    @Resource
    private projectService projectService;

    @Resource
    private productService productService;

    @GetMapping("/downloadTemplate")
    public void downloadTemplate(HttpServletResponse response) {
        try {
            // 1. 设置响应头
            String fileName = URLEncoder.encode("项目导入模板.xlsx", StandardCharsets.UTF_8);
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
            // 2. 创建空列表，生成模板只写表头
            List<ProjectExcelDTO> emptyList = new ArrayList<>();
            // 3. 写入 Excel
            EasyExcel.write(response.getOutputStream(), ProjectExcelDTO.class)
                    .sheet("模板")
                    .doWrite(emptyList);
        } catch (IOException e) {
           BizAsserts.fail("下载模板失败: " + e.getMessage());
        }
    }

    @GetMapping("/downloadProdTemplate")
    public void downloadProdTemplate(@RequestParam String productType,
                                     HttpServletResponse response) {
        try {
            // 设置响应头
            String fileName = URLEncoder.encode("产品导入模板-" + productType + ".xlsx", StandardCharsets.UTF_8);
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
            // 根据产品类型动态生成模板
            Class<?> dtoClass;
            List<?> emptyList = switch (productType) {
                case "HIC" -> {
                    dtoClass = HicExcelDTO.class;
                    yield new ArrayList<HicExcelDTO>();
                }
                case "高硅氧" -> {
                    dtoClass = GgyExcelDTO.class;
                    yield new ArrayList<GgyExcelDTO>();
                }
                case "涂层" -> {
                    dtoClass = TcExcelDTO.class;
                    yield new ArrayList<TcExcelDTO>();
                }
                case "结构复材" -> {
                    dtoClass = JgfcExcelDTO.class;
                    yield new ArrayList<JgfcExcelDTO>();
                }
                case "电气" -> {
                    dtoClass = DqExcelDTO.class;
                    yield new ArrayList<DqExcelDTO>();
                }
                case "力热" -> {
                    dtoClass = LrExcelDTO.class;
                    yield new ArrayList<LrExcelDTO>();
                }
                // 更多类型可以在此扩展
                default -> throw new IllegalArgumentException("不支持的产品类型: " + productType);
            };
            // 写出 Excel（可根据类型注册不同的下拉处理器）
            EasyExcel.write(response.getOutputStream(), dtoClass)
                    .registerWriteHandler(new ProductTemplateDropdownWriteHandler()) // 如有通用的下拉处理器
                    .sheet("模板")
                    .doWrite(emptyList);
        } catch (IOException | IllegalArgumentException e) {
            // 统一抛出异常
            BizAsserts.fail("下载模板失败: " + e.getMessage());
        }
    }


    @PostMapping("/importProjExcel")
    public CommonResult<String> importExcel(@RequestParam("file") MultipartFile file) {
        try {
            // 1. 读取 Excel 转为 DTO 列表
            List<ProjectExcelDTO> dtoList = EasyExcel.read(file.getInputStream())
                    .head(ProjectExcelDTO.class)
                    .sheet()
                    .doReadSync();
            if (CollectionUtils.isEmpty(dtoList)) {
                return CommonResult.failed("Excel内容为空");
            }
            // 2. 校验导入数据中的重复项
            Set<String> codeSet = new HashSet<>();
            Set<String> nameSet = new HashSet<>();
            for (ProjectExcelDTO dto : dtoList) {
                if (!codeSet.add(dto.getCode())) {
                    return CommonResult.failed("导入数据中存在重复项目代号: " + dto.getCode());
                }
                if (!nameSet.add(dto.getName())) {
                    return CommonResult.failed("导入数据中存在重复项目名称: " + dto.getName());
                }
            }
            // 3. 查询数据库是否已有重复
            List<Project> existing = projectService.lambdaQuery()
                    .in(Project::getCode, codeSet)
                    .or()
                    .in(Project::getName, nameSet)
                    .list();
            for (Project exist : existing) {
                if (codeSet.contains(exist.getCode())) {
                    return CommonResult.failed("项目代号已存在: " + exist.getCode());
                }
                if (nameSet.contains(exist.getName())) {
                    return CommonResult.failed("项目名称已存在: " + exist.getName());
                }
            }
            List<Project> projectList = dtoList.stream().map(dto -> {
                Project project = new Project();
                project.setCode(dto.getCode());
                project.setName(dto.getName());
                project.setClient(dto.getClient());
                project.setClientUsername(dto.getClientUsername());
                project.setStartTime(dto.getStartTime());
                project.setExDeliveryTime(dto.getExDeliveryTime());
                project.setTrDeliveryTime(dto.getTrDeliveryTime());
                project.setStatus(dto.getStatus());
                project.setRemark(dto.getRemark());
                return project;
            }).collect(Collectors.toList());
            // 5. 批量保存
            projectService.saveBatch(projectList);
            return CommonResult.success("导入成功，共 " + projectList.size() + " 条记录");
        } catch (IOException e) {
            return CommonResult.failed("Excel读取失败: " + e.getMessage());
        } catch (Exception ex) {
            return CommonResult.failed("导入失败: " + ex.getMessage());
        }
    }

    @PostMapping("/importProDExcelHic")
    public CommonResult<String> importProDExcelHic(@RequestParam("file") MultipartFile file) {
        try {
            // 1. 读取 Excel 转为 DTO 列表
            List<HicExcelDTO> dtoList = EasyExcel.read(file.getInputStream())
                    .head(HicExcelDTO.class)
                    .sheet()
                    .doReadSync();

            if (CollectionUtils.isEmpty(dtoList)) {
                return CommonResult.failed("Excel内容为空");
            }
            // 2. 获取所有 projectName 并去重
            Set<String> projectNameSet = dtoList.stream()
                    .map(HicExcelDTO::getProjectName)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toSet());
            // 3. 查询数据库中存在的项目
            List<Project> existProjects = projectService.lambdaQuery()
                    .in(Project::getName, projectNameSet)
                    .list();
            Map<String, Long> nameIdMap = existProjects.stream()
                    .collect(Collectors.toMap(Project::getName, Project::getId));
            // 4. 检查是否有未匹配的项目名称
            for (String name : projectNameSet) {
                if (!nameIdMap.containsKey(name)) {
                    return CommonResult.failed("项目名称不存在: " + name);
                }
            }
            // 阶段顺序和名称
            String[] stageNames = {"立项", "材料准备", "模具生产", "预制生产", "RTM成型", "套装", "加工", "检验", "发货"};
            // 5. DTO 转实体，并组装 ganttConfig
            List<Product> productList = dtoList.stream().map(dto -> {
                Product product = new Product();
                product.setProjectId(nameIdMap.get(dto.getProjectName()));
                product.setName(dto.getName());
                product.setType(dto.getType());
                product.setAmount(dto.getAmount());
                product.setFinishAmount(dto.getFinishAmount());
                List<GanttConfigDto> ganttConfig = new ArrayList<>();
                for (int i = 0; i < stageNames.length; i++) {
                    GanttConfigDto config = new GanttConfigDto();
                    config.setId(i + 1);
                    config.setName(stageNames[i]);
                    List<String> times = new ArrayList<>();
                    switch (stageNames[i]) {
                        case "立项":
                            times.add(dto.getProjectInitiationStart() == null ? null : dto.getProjectInitiationStart().toString());
                            times.add(dto.getProjectInitiationEnd() == null ? null : dto.getProjectInitiationEnd().toString());
                            System.out.println(dto.getProjectInitiationStart());
                            break;
                        case "材料准备":
                            times.add(dto.getDocumentPreparationStart() == null ? null : dto.getDocumentPreparationStart().toString());
                            times.add(dto.getDocumentPreparationEnd() == null ? null : dto.getDocumentPreparationEnd().toString());
                            System.out.println(dto.getDocumentPreparationStart());
                            break;
                        case "模具生产":
                            times.add(dto.getMoldDesignStart() == null ? null : dto.getMoldDesignStart().toString());
                            times.add(dto.getMoldDesignEnd() == null ? null : dto.getMoldDesignEnd().toString());
                            System.out.println(dto.getMoldDesignStart());
                            break;
                        case "预制生产":
                            times.add(dto.getPreProductionStart() == null ? null : dto.getPreProductionStart().toString());
                            times.add(dto.getPreProductionEnd() == null ? null : dto.getPreProductionEnd().toString());
                            System.out.println(dto.getPreProductionStart());
                            break;
                        case "RTM成型":
                            times.add(dto.getRtmProcessStart() == null ? null : dto.getRtmProcessStart().toString());
                            times.add(dto.getRtmProcessEnd() == null ? null : dto.getRtmProcessEnd().toString());
                            System.out.println(dto.getRtmProcessStart());
                            break;
                        case "套装":
                            times.add(dto.getSetStart() == null ? null : dto.getSetStart().toString());
                            times.add(dto.getSetEnd() == null ? null : dto.getSetEnd().toString());
                            System.out.println(dto.getSetStart());
                            break;
                        case "加工":
                            times.add(dto.getProcessingStart() == null ? null : dto.getProcessingStart().toString());
                            times.add(dto.getProcessingEnd() == null ? null : dto.getProcessingEnd().toString());
                            System.out.println(dto.getProcessingStart());
                            break;
                        case "检验":
                            times.add(dto.getInspectionStart() == null ? null : dto.getInspectionStart().toString());
                            times.add(dto.getInspectionEnd() == null ? null : dto.getInspectionEnd().toString());
                            System.out.println(dto.getInspectionStart());
                            break;
                        case "发货":
                            times.add(dto.getDeliveryStart() == null ? null : dto.getDeliveryStart().toString());
                            times.add(dto.getDeliveryEnd() == null ? null : dto.getDeliveryEnd().toString());
                            System.out.println(dto.getDeliveryStart());
                            break;
                    }
                    config.setTime(times);

                    ganttConfig.add(config);
                }
                product.setGanttConfig(ganttConfig);
                return product;
            }).collect(Collectors.toList());
            // 6. 批量保存
            productService.saveBatch(productList);
            return CommonResult.success("导入成功，共 " + productList.size() + " 条记录");
        } catch (IOException e) {
            return CommonResult.failed("Excel读取失败: " + e.getMessage());
        } catch (Exception ex) {
            return CommonResult.failed("导入失败: " + ex.getMessage());
        }
    }

    @PostMapping("/importProDExcelGgy")
    public CommonResult<String> importProDExcelGgy(@RequestParam("file") MultipartFile file) {
        try {
            // 1. 读取 Excel 转为 DTO 列表
            List<GgyExcelDTO> dtoList = EasyExcel.read(file.getInputStream())
                    .head(GgyExcelDTO.class)
                    .sheet()
                    .doReadSync();

            if (CollectionUtils.isEmpty(dtoList)) {
                return CommonResult.failed("Excel内容为空");
            }
            // 2. 获取所有 projectName 并去重
            Set<String> projectNameSet = dtoList.stream()
                    .map(GgyExcelDTO::getProjectName)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toSet());
            // 3. 查询数据库中存在的项目
            List<Project> existProjects = projectService.lambdaQuery()
                    .in(Project::getName, projectNameSet)
                    .list();
            Map<String, Long> nameIdMap = existProjects.stream()
                    .collect(Collectors.toMap(Project::getName, Project::getId));
            // 4. 检查是否有未匹配的项目名称
            for (String name : projectNameSet) {
                if (!nameIdMap.containsKey(name)) {
                    return CommonResult.failed("项目名称不存在: " + name);
                }
            }
            // 阶段顺序和名称
            String[] stageNames = {"立项", "材料准备", "材料生产", "加工", "检验", "发货"};
            // 5. DTO 转实体，并组装 ganttConfig
            List<Product> productList = dtoList.stream().map(dto -> {
                Product product = new Product();
                product.setProjectId(nameIdMap.get(dto.getProjectName()));
                product.setName(dto.getName());
                product.setType(dto.getType());
                product.setAmount(dto.getAmount());
                product.setFinishAmount(dto.getFinishAmount());
                List<GanttConfigDto> ganttConfig = new ArrayList<>();
                for (int i = 0; i < stageNames.length; i++) {
                    GanttConfigDto config = new GanttConfigDto();
                    config.setId(i + 1);
                    config.setName(stageNames[i]);
                    List<String> times = new ArrayList<>();
                    switch (stageNames[i]) {
                        case "立项":
                            times.add(dto.getProjectInitiationStart() == null ? null : dto.getProjectInitiationStart().toString());
                            times.add(dto.getProjectInitiationEnd() == null ? null : dto.getProjectInitiationEnd().toString());
                            System.out.println(dto.getProjectInitiationStart());
                            break;
                        case "材料准备":
                            times.add(dto.getDocumentPreparationStart() == null ? null : dto.getDocumentPreparationStart().toString());
                            times.add(dto.getDocumentPreparationEnd() == null ? null : dto.getDocumentPreparationEnd().toString());
                            System.out.println(dto.getDocumentPreparationStart());
                            break;
                        case "材料生产":
                            times.add(dto.getDocumentDesignStart() == null ? null : dto.getDocumentDesignStart().toString());
                            times.add(dto.getDocumentDesignEnd() == null ? null : dto.getDocumentDesignEnd().toString());
                            System.out.println(dto.getDocumentDesignStart());
                            break;
                        case "加工":
                            times.add(dto.getProcessingStart() == null ? null : dto.getProcessingStart().toString());
                            times.add(dto.getProcessingEnd() == null ? null : dto.getProcessingEnd().toString());
                            System.out.println(dto.getProcessingStart());
                            break;
                        case "检验":
                            times.add(dto.getInspectionStart() == null ? null : dto.getInspectionStart().toString());
                            times.add(dto.getInspectionEnd() == null ? null : dto.getInspectionEnd().toString());
                            System.out.println(dto.getInspectionStart());
                            break;
                        case "发货":
                            times.add(dto.getDeliveryStart() == null ? null : dto.getDeliveryStart().toString());
                            times.add(dto.getDeliveryEnd() == null ? null : dto.getDeliveryEnd().toString());
                            System.out.println(dto.getDeliveryStart());
                            break;
                    }
                    config.setTime(times);
                    ganttConfig.add(config);
                }
                product.setGanttConfig(ganttConfig);
                return product;
            }).collect(Collectors.toList());
            // 6. 批量保存
            productService.saveBatch(productList);
            return CommonResult.success("导入成功，共 " + productList.size() + " 条记录");
        } catch (IOException e) {
            return CommonResult.failed("Excel读取失败: " + e.getMessage());
        } catch (Exception ex) {
            return CommonResult.failed("导入失败: " + ex.getMessage());
        }
    }

    @PostMapping("/importProDExcelTc")
    public CommonResult<String> importProDExcelTc(@RequestParam("file") MultipartFile file) {
        try {
            // 1. 读取 Excel 转为 DTO 列表
            List<TcExcelDTO> dtoList = EasyExcel.read(file.getInputStream())
                    .head(TcExcelDTO.class)
                    .sheet()
                    .doReadSync();

            if (CollectionUtils.isEmpty(dtoList)) {
                return CommonResult.failed("Excel内容为空");
            }
            // 2. 获取所有 projectName 并去重
            Set<String> projectNameSet = dtoList.stream()
                    .map(TcExcelDTO::getProjectName)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toSet());
            // 3. 查询数据库中存在的项目
            List<Project> existProjects = projectService.lambdaQuery()
                    .in(Project::getName, projectNameSet)
                    .list();
            Map<String, Long> nameIdMap = existProjects.stream()
                    .collect(Collectors.toMap(Project::getName, Project::getId));
            // 4. 检查是否有未匹配的项目名称
            for (String name : projectNameSet) {
                if (!nameIdMap.containsKey(name)) {
                    return CommonResult.failed("项目名称不存在: " + name);
                }
            }
            // 阶段顺序和名称
            String[] stageNames = {"立项", "材料准备", "生产", "检验", "发货"};
            // 5. DTO 转实体，并组装 ganttConfig
            List<Product> productList = dtoList.stream().map(dto -> {
                Product product = new Product();
                product.setProjectId(nameIdMap.get(dto.getProjectName()));
                product.setName(dto.getName());
                product.setType(dto.getType());
                product.setAmount(dto.getAmount());
                product.setFinishAmount(dto.getFinishAmount());
                List<GanttConfigDto> ganttConfig = new ArrayList<>();
                for (int i = 0; i < stageNames.length; i++) {
                    GanttConfigDto config = new GanttConfigDto();
                    config.setId(i + 1);
                    config.setName(stageNames[i]);
                    List<String> times = new ArrayList<>();
                    switch (stageNames[i]) {
                        case "立项":
                            times.add(dto.getProjectInitiationStart() == null ? null : dto.getProjectInitiationStart().toString());
                            times.add(dto.getProjectInitiationEnd() == null ? null : dto.getProjectInitiationEnd().toString());
                            System.out.println(dto.getProjectInitiationStart());
                            break;
                        case "材料准备":
                            times.add(dto.getDocumentPreparationStart() == null ? null : dto.getDocumentPreparationStart().toString());
                            times.add(dto.getDocumentPreparationEnd() == null ? null : dto.getDocumentPreparationEnd().toString());
                            System.out.println(dto.getDocumentPreparationStart());
                            break;
                        case "生产":
                            times.add(dto.getDesignStart() == null ? null : dto.getDesignStart().toString());
                            times.add(dto.getDesignEnd() == null ? null : dto.getDesignEnd().toString());
                            System.out.println(dto.getDesignStart());
                            break;
                        case "检验":
                            times.add(dto.getInspectionStart() == null ? null : dto.getInspectionStart().toString());
                            times.add(dto.getInspectionEnd() == null ? null : dto.getInspectionEnd().toString());
                            System.out.println(dto.getInspectionStart());
                            break;
                        case "发货":
                            times.add(dto.getDeliveryStart() == null ? null : dto.getDeliveryStart().toString());
                            times.add(dto.getDeliveryEnd() == null ? null : dto.getDeliveryEnd().toString());
                            System.out.println(dto.getDeliveryStart());
                            break;
                    }
                    config.setTime(times);
                    ganttConfig.add(config);
                }
                product.setGanttConfig(ganttConfig);
                return product;
            }).collect(Collectors.toList());
            // 6. 批量保存
            productService.saveBatch(productList);
            return CommonResult.success("导入成功，共 " + productList.size() + " 条记录");
        } catch (IOException e) {
            return CommonResult.failed("Excel读取失败: " + e.getMessage());
        } catch (Exception ex) {
            return CommonResult.failed("导入失败: " + ex.getMessage());
        }
    }

    @PostMapping("/importProDExcelJgfc")
    public CommonResult<String> importProDExcelJgfc(@RequestParam("file") MultipartFile file) {
        try {
            // 1. 读取 Excel 转为 DTO 列表
            List<JgfcExcelDTO> dtoList = EasyExcel.read(file.getInputStream())
                    .head(JgfcExcelDTO.class)
                    .sheet()
                    .doReadSync();

            if (CollectionUtils.isEmpty(dtoList)) {
                return CommonResult.failed("Excel内容为空");
            }
            // 2. 获取所有 projectName 并去重
            Set<String> projectNameSet = dtoList.stream()
                    .map(JgfcExcelDTO::getProjectName)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toSet());
            // 3. 查询数据库中存在的项目
            List<Project> existProjects = projectService.lambdaQuery()
                    .in(Project::getName, projectNameSet)
                    .list();
            Map<String, Long> nameIdMap = existProjects.stream()
                    .collect(Collectors.toMap(Project::getName, Project::getId));
            // 4. 检查是否有未匹配的项目名称
            for (String name : projectNameSet) {
                if (!nameIdMap.containsKey(name)) {
                    return CommonResult.failed("项目名称不存在: " + name);
                }
            }
            // 阶段顺序和名称
            String[] stageNames = {"立项", "材料准备", "模具生产", "铺贴固化",  "加工", "检验", "发货"};
            // 5. DTO 转实体，并组装 ganttConfig
            List<Product> productList = dtoList.stream().map(dto -> {
                Product product = new Product();
                product.setProjectId(nameIdMap.get(dto.getProjectName()));
                product.setName(dto.getName());
                product.setType(dto.getType());
                product.setAmount(dto.getAmount());
                product.setFinishAmount(dto.getFinishAmount());
                List<GanttConfigDto> ganttConfig = new ArrayList<>();
                for (int i = 0; i < stageNames.length; i++) {
                    GanttConfigDto config = new GanttConfigDto();
                    config.setId(i + 1);
                    config.setName(stageNames[i]);
                    List<String> times = new ArrayList<>();
                    switch (stageNames[i]) {
                        case "立项":
                            times.add(dto.getProjectInitiationStart() == null ? null : dto.getProjectInitiationStart().toString());
                            times.add(dto.getProjectInitiationEnd() == null ? null : dto.getProjectInitiationEnd().toString());
                            System.out.println(dto.getProjectInitiationStart());
                            break;
                        case "材料准备":
                            times.add(dto.getDocumentPreparationStart() == null ? null : dto.getDocumentPreparationStart().toString());
                            times.add(dto.getDocumentPreparationEnd() == null ? null : dto.getDocumentPreparationEnd().toString());
                            System.out.println(dto.getDocumentPreparationStart());
                            break;
                        case "模具生产":
                            times.add(dto.getMoldDesignStart() == null ? null : dto.getMoldDesignStart().toString());
                            times.add(dto.getMoldDesignEnd() == null ? null : dto.getMoldDesignEnd().toString());
                            System.out.println(dto.getMoldDesignStart());
                            break;
                        case "铺贴固化":
                            times.add(dto.getPavingCuringStart() == null ? null : dto.getPavingCuringStart().toString());
                            times.add(dto.getPavingCuringEnd() == null ? null : dto.getPavingCuringEnd().toString());
                            System.out.println(dto.getPavingCuringStart());
                            break;
                        case "加工":
                            times.add(dto.getProcessingStart() == null ? null : dto.getProcessingStart().toString());
                            times.add(dto.getProcessingEnd() == null ? null : dto.getProcessingEnd().toString());
                            System.out.println(dto.getProcessingStart());
                            break;
                        case "检验":
                            times.add(dto.getInspectionStart() == null ? null : dto.getInspectionStart().toString());
                            times.add(dto.getInspectionEnd() == null ? null : dto.getInspectionEnd().toString());
                            System.out.println(dto.getInspectionStart());
                            break;
                        case "发货":
                            times.add(dto.getDeliveryStart() == null ? null : dto.getDeliveryStart().toString());
                            times.add(dto.getDeliveryEnd() == null ? null : dto.getDeliveryEnd().toString());
                            System.out.println(dto.getDeliveryStart());
                            break;
                    }
                    config.setTime(times);

                    ganttConfig.add(config);
                }
                product.setGanttConfig(ganttConfig);
                return product;
            }).collect(Collectors.toList());
            // 6. 批量保存
            productService.saveBatch(productList);
            return CommonResult.success("导入成功，共 " + productList.size() + " 条记录");
        } catch (IOException e) {
            return CommonResult.failed("Excel读取失败: " + e.getMessage());
        } catch (Exception ex) {
            return CommonResult.failed("导入失败: " + ex.getMessage());
        }
    }

    @PostMapping("/importProDExcelDq")
    public CommonResult<String> importProDExcelDq(@RequestParam("file") MultipartFile file) {
        try {
            // 1. 读取 Excel 转为 DTO 列表
            List<DqExcelDTO> dtoList = EasyExcel.read(file.getInputStream())
                    .head(DqExcelDTO.class)
                    .sheet()
                    .doReadSync();
            if (CollectionUtils.isEmpty(dtoList)) {
                return CommonResult.failed("Excel内容为空");
            }
            // 2. 获取所有 projectName 并去重
            Set<String> projectNameSet = dtoList.stream()
                    .map(DqExcelDTO::getProjectName)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toSet());
            // 3. 查询数据库中存在的项目
            List<Project> existProjects = projectService.lambdaQuery()
                    .in(Project::getName, projectNameSet)
                    .list();
            Map<String, Long> nameIdMap = existProjects.stream()
                    .collect(Collectors.toMap(Project::getName, Project::getId));
            // 4. 检查是否有未匹配的项目名称
            for (String name : projectNameSet) {
                if (!nameIdMap.containsKey(name)) {
                    return CommonResult.failed("项目名称不存在: " + name);
                }
            }
            // 阶段顺序和名称
            String[] stageNames = {"立项", "材料准备", "生产", "验收试验", "检验", "发货"};
            // 5. DTO 转实体，并组装 ganttConfig
            List<Product> productList = dtoList.stream().map(dto -> {
                Product product = new Product();
                product.setProjectId(nameIdMap.get(dto.getProjectName()));
                product.setName(dto.getName());
                product.setType(dto.getType());
                product.setAmount(dto.getAmount());
                product.setFinishAmount(dto.getFinishAmount());
                List<GanttConfigDto> ganttConfig = new ArrayList<>();
                for (int i = 0; i < stageNames.length; i++) {
                    GanttConfigDto config = new GanttConfigDto();
                    config.setId(i + 1);
                    config.setName(stageNames[i]);
                    List<String> times = new ArrayList<>();
                    switch (stageNames[i]) {
                        case "立项":
                            times.add(dto.getProjectInitiationStart() == null ? null : dto.getProjectInitiationStart().toString());
                            times.add(dto.getProjectInitiationEnd() == null ? null : dto.getProjectInitiationEnd().toString());
                            System.out.println(dto.getProjectInitiationStart());
                            break;
                        case "材料准备":
                            times.add(dto.getDocumentPreparationStart() == null ? null : dto.getDocumentPreparationStart().toString());
                            times.add(dto.getDocumentPreparationEnd() == null ? null : dto.getDocumentPreparationEnd().toString());
                            System.out.println(dto.getDocumentPreparationStart());
                            break;
                        case "生产":
                            times.add(dto.getDesignStart() == null ? null : dto.getDesignStart().toString());
                            times.add(dto.getDesignEnd() == null ? null : dto.getDesignEnd().toString());
                            System.out.println(dto.getDesignStart());
                            break;
                        case "验收试验":
                            times.add(dto.getAcceptanceTestStart() == null ? null : dto.getAcceptanceTestStart().toString());
                            times.add(dto.getAcceptanceTestEnd() == null ? null : dto.getAcceptanceTestEnd().toString());
                            System.out.println(dto.getAcceptanceTestStart());
                            break;
                        case "检验":
                            times.add(dto.getInspectionStart() == null ? null : dto.getInspectionStart().toString());
                            times.add(dto.getInspectionEnd() == null ? null : dto.getInspectionEnd().toString());
                            System.out.println(dto.getInspectionStart());
                            break;
                        case "发货":
                            times.add(dto.getDeliveryStart() == null ? null : dto.getDeliveryStart().toString());
                            times.add(dto.getDeliveryEnd() == null ? null : dto.getDeliveryEnd().toString());
                            System.out.println(dto.getDeliveryStart());
                            break;
                    }
                    config.setTime(times);

                    ganttConfig.add(config);
                }
                product.setGanttConfig(ganttConfig);
                return product;
            }).collect(Collectors.toList());
            // 6. 批量保存
            productService.saveBatch(productList);
            return CommonResult.success("导入成功，共 " + productList.size() + " 条记录");
        } catch (IOException e) {
            return CommonResult.failed("Excel读取失败: " + e.getMessage());
        } catch (Exception ex) {
            return CommonResult.failed("导入失败: " + ex.getMessage());
        }
    }

    @PostMapping("/importProDExcelLr")
    public CommonResult<String> importProDExcelLr(@RequestParam("file") MultipartFile file) {
        try {
            // 1. 读取 Excel 转为 DTO 列表
            List<LrExcelDTO> dtoList = EasyExcel.read(file.getInputStream())
                    .head(LrExcelDTO.class)
                    .sheet()
                    .doReadSync();
            if (CollectionUtils.isEmpty(dtoList)) {
                return CommonResult.failed("Excel内容为空");
            }
            // 2. 获取所有 projectName 并去重
            Set<String> projectNameSet = dtoList.stream()
                    .map(LrExcelDTO::getProjectName)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toSet());
            // 3. 查询数据库中存在的项目
            List<Project> existProjects = projectService.lambdaQuery()
                    .in(Project::getName, projectNameSet)
                    .list();
            Map<String, Long> nameIdMap = existProjects.stream()
                    .collect(Collectors.toMap(Project::getName, Project::getId));
            // 4. 检查是否有未匹配的项目名称
            for (String name : projectNameSet) {
                if (!nameIdMap.containsKey(name)) {
                    return CommonResult.failed("项目名称不存在: " + name);
                }
            }
            // 阶段顺序和名称
            String[] stageNames = {"立项", "材料准备", "工装准备", "试验调试", "试验", "试验报告"};
            // 5. DTO 转实体，并组装 ganttConfig
            List<Product> productList = dtoList.stream().map(dto -> {
                Product product = new Product();
                product.setProjectId(nameIdMap.get(dto.getProjectName()));
                product.setName(dto.getName());
                product.setType(dto.getType());
                product.setAmount(dto.getAmount());
                product.setFinishAmount(dto.getFinishAmount());
                List<GanttConfigDto> ganttConfig = new ArrayList<>();
                for (int i = 0; i < stageNames.length; i++) {
                    GanttConfigDto config = new GanttConfigDto();
                    config.setId(i + 1);
                    config.setName(stageNames[i]);
                    List<String> times = new ArrayList<>();
                    switch (stageNames[i]) {
                        case "立项":
                            times.add(dto.getProjectInitiationStart() == null ? null : dto.getProjectInitiationStart().toString());
                            times.add(dto.getProjectInitiationEnd() == null ? null : dto.getProjectInitiationEnd().toString());
                            System.out.println(dto.getProjectInitiationStart());
                            break;
                        case "材料准备":
                            times.add(dto.getDocumentPreparationStart() == null ? null : dto.getDocumentPreparationStart().toString());
                            times.add(dto.getDocumentPreparationEnd() == null ? null : dto.getDocumentPreparationEnd().toString());
                            System.out.println(dto.getDocumentPreparationStart());
                            break;
                        case "工装准备":
                            times.add(dto.getWorkwearPreparationStart() == null ? null : dto.getWorkwearPreparationStart().toString());
                            times.add(dto.getWorkwearPreparationEnd() == null ? null : dto.getWorkwearPreparationEnd().toString());
                            System.out.println(dto.getWorkwearPreparationStart());
                            break;
                        case "试验调试":
                            times.add(dto.getTestDebugStart() == null ? null : dto.getTestDebugStart().toString());
                            times.add(dto.getTestDebugEnd() == null ? null : dto.getTestDebugEnd().toString());
                            System.out.println(dto.getTestDebugStart());
                            break;
                        case "试验":
                            times.add(dto.getTestStart() == null ? null : dto.getTestStart().toString());
                            times.add(dto.getTestEnd() == null ? null : dto.getTestEnd().toString());
                            System.out.println(dto.getTestStart());
                            break;
                        case "试验报告":
                            times.add(dto.getTestReportStart() == null ? null : dto.getTestReportStart().toString());
                            times.add(dto.getTestReportEnd() == null ? null : dto.getTestReportEnd().toString());
                            System.out.println(dto.getTestReportStart());
                            break;
                    }
                    config.setTime(times);

                    ganttConfig.add(config);
                }
                product.setGanttConfig(ganttConfig);
                return product;
            }).collect(Collectors.toList());
            // 6. 批量保存
            productService.saveBatch(productList);
            return CommonResult.success("导入成功，共 " + productList.size() + " 条记录");
        } catch (IOException e) {
            return CommonResult.failed("Excel读取失败: " + e.getMessage());
        } catch (Exception ex) {
            return CommonResult.failed("导入失败: " + ex.getMessage());
        }
    }


}
